package com.zone.domain.strategy.service.raffle.impl;

import com.zone.domain.strategy.model.entity.RaffleParamEntity;
import com.zone.domain.strategy.model.entity.RaffleResultEntity;
import com.zone.domain.strategy.model.entity.StrategyAwardEntity;
import com.zone.domain.strategy.model.valobj.RuleActionEnum;
import com.zone.domain.strategy.repository.IStrategyRepository;
import com.zone.domain.strategy.service.armory.IStrategyDispatch;
import com.zone.domain.strategy.service.IRaffleStrategy;
import com.zone.domain.strategy.service.rule.chain.RaffleRuleFilterChain;
import com.zone.domain.strategy.service.rule.tree.factory.DefaultTreeNodeFactory;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.Validate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Objects;

/**
 * @author: zongzi
 * @description: 抽象的抽奖策略，提供抽奖的流程与公共实现
 * @date: 2024/6/3
 */
@Slf4j
@Service
public abstract class AbstractRaffleStrategy implements IRaffleStrategy {
    @Autowired
    private IStrategyRepository strategyRepository;
    @Autowired
    private IStrategyDispatch strategyDispatch;

    @Override
    public RaffleResultEntity raffle(RaffleParamEntity param) {
        Validate.notNull(param.getStrategyId(), "策略id不能为空");
        Validate.notNull(param.getUserId(), "用户id不能为空");

        // 执行抽奖前置过滤器链
        RaffleRuleFilterChain.StrategyAwardVO strategyAwardByChain = executeFilterChainBeforeRaffle(param.getStrategyId(), param.getUserId());
        if (Objects.nonNull(strategyAwardByChain) && Objects.equals(strategyAwardByChain.getRuleAction(), RuleActionEnum.INTERCEPT)) {
            // 直接返回（黑名单、权重为必中奖。不单独考虑库存与其他情况）
            StrategyAwardEntity strategyAward = strategyRepository.getStrategyAward(param.getStrategyId(), strategyAwardByChain.getAwardId());
            return RaffleResultEntity.builder()
                    .awardId(strategyAwardByChain.getAwardId())
                    .awardConfig(strategyAwardByChain.getAwardConfig())
                    .sort(strategyAward.getSort())
                    .awardTitle(strategyAward.getAwardTitle())
                    .build();
        }

        // 未被抽奖过滤前置处理器处理，根据策略id随机获取奖品
        Integer awardId = strategyDispatch.getRandomAwardId(param.getStrategyId());

        // 执行抽奖规则树，对抽到的奖品进行规则树处理
        DefaultTreeNodeFactory.StrategyAwardVO strategyAwardByTree = executeRuleTreeRaffle(param.getStrategyId(), param.getUserId(), awardId);

        // 返回最终处理
        StrategyAwardEntity strategyAward = strategyRepository.getStrategyAward(param.getStrategyId(), strategyAwardByTree.getAwardId());
        return RaffleResultEntity.builder()
                .awardId(strategyAwardByTree.getAwardId())
                .awardTitle(strategyAward.getAwardTitle())
                .awardConfig(strategyAwardByTree.getAwardRuleValue())
                .sort(strategyAward.getSort())
                .build();
    }

    // 抽奖前执行过滤器链
    public abstract RaffleRuleFilterChain.StrategyAwardVO executeFilterChainBeforeRaffle(Long strategyId, String userId);

    // 执行规则树
    public abstract DefaultTreeNodeFactory.StrategyAwardVO executeRuleTreeRaffle(Long strategyId, String userId, Integer awardId);
}
